﻿/* 2013/1/6 */
using System;
using System.Collections.Generic;

namespace Cosmos.Media.Play
{
    /// <summary>
    /// Represents a item shown in play list.
    /// </summary>
    public class PlayListItem : IPlayEntity
    {
        private string _name;
        private string _path;

        private PlayList _list;

        private PlayTagCollection _tags;
        private PlayAttributeCollection _attributes;

        private PlayListItem()
        {
            _tags = new PlayTagCollection(this);
            _attributes = new PlayAttributeCollection(this);
        }

        /// <summary>
        /// Initializes a new instance of PlayListItem class with specified name and file path.
        /// </summary>
        /// <param name="name">Name of the item.</param>
        /// <param name="path">File path of the item.</param>
        public PlayListItem(string name, string path)
            : this()
        {
            _name = name;
            _path = path;
        }

        private List<PlayAttribute> GetInheritedAttributes()
        {
            LinkedList<PlayAttribute> inheritedAttributeLinkedList = new LinkedList<PlayAttribute>();
            HashSet<string> singleAttributeNames = new HashSet<string>();
            HashSet<string> multipleAttributeNames = new HashSet<string>();

            foreach (PlayAttribute anAttribute in _attributes)
            {
                if (anAttribute.AllowMultiple)
                {
                    multipleAttributeNames.Add(anAttribute.Name);
                }
                else
                {
                    singleAttributeNames.Add(anAttribute.Name);
                }
            }

            PlayTreeNode parentNode = null;
            if (List != null)
            {
                parentNode = List.Node;
            }

            while (parentNode != null)
            {
                LinkedListNode<PlayAttribute> addedListNode = null;
                foreach (PlayAttribute anAttribute in parentNode.Attributes)
                {
                    if (anAttribute.Inherited)
                    {
                        if (anAttribute.AllowMultiple
                            && !singleAttributeNames.Contains(anAttribute.Name))
                        {
                            multipleAttributeNames.Add(anAttribute.Name);

                            if (addedListNode == null)
                            {
                                addedListNode = inheritedAttributeLinkedList.AddFirst(anAttribute);
                            }
                            else
                            {
                                addedListNode = inheritedAttributeLinkedList.AddAfter(addedListNode, anAttribute);
                            }
                        }
                        else if (!anAttribute.AllowMultiple
                            && !multipleAttributeNames.Contains(anAttribute.Name)
                            && !singleAttributeNames.Contains(anAttribute.Name))
                        {
                            singleAttributeNames.Add(anAttribute.Name);

                            if (addedListNode == null)
                            {
                                addedListNode = inheritedAttributeLinkedList.AddFirst(anAttribute);
                            }
                            else
                            {
                                addedListNode = inheritedAttributeLinkedList.AddAfter(addedListNode, anAttribute);
                            }
                        }
                    }
                }

                parentNode = parentNode.ParentNode;
            }


            List<PlayAttribute> inheritedAttributeList = new List<PlayAttribute>(inheritedAttributeLinkedList.Count);
            foreach (PlayAttribute anAttribute in inheritedAttributeLinkedList)
            {
                inheritedAttributeList.Add(anAttribute);
            }
            return inheritedAttributeList;
        }

        /// <summary>
        /// Gets the PlayList which contains this play list item.
        /// </summary>
        public PlayList List
        {
            get
            {
                return _list;
            }

            internal set
            {
                _list = value;
            }
        }

        /// <summary>
        /// Gets or sets the name of the item.
        /// </summary>
        public string Name
        {
            get
            { 
                return _name;
            }

            set
            {
                _name = value;
            }
        }

        /// <summary>
        /// Gets the file path of the item.
        /// </summary>
        public string Path
        {
            get
            { 
                return _path; 
            }

            protected set
            {
                _path = value;
            }
        }

        /// <summary>
        /// Gets or sets the play time of the item.
        /// </summary>
        /*public TimeSpan Time
        {
            get
            {
                return _time;
            }

            set
            {
                _time = value;
            }
        }*/

        /// <summary>
        /// Gets collection that contains tags of this play list item.
        /// </summary>
        public PlayTagCollection Tags
        {
            get
            {
                return _tags;
            }

            protected set
            {
                if (value != null)
                    _tags = value;
            }
        }

        /// <summary>
        /// Gets a collection that contains attributes of this play list item.
        /// </summary>
        public PlayAttributeCollection Attributes
        {
            get
            {
                return _attributes;
            }

            protected set
            {
                if (value != null)
                    _attributes = value;
            }
        }

        /// <summary>
        /// Gets inherited attributes from all parent nodes.
        /// </summary>
        public IList<PlayAttribute> InheritedAttributes
        {
            get
            {
                return GetInheritedAttributes();
            }
        }
    }
}
